﻿namespace Onetube.Providers
{
    using Newtonsoft.Json.Linq;
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Threading;
    using System.Threading.Tasks;

    public static class YouTube
    {
        private const string BotUserAgent = "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)";
        public const VideoQuality DefaultMinQuality = VideoQuality.Medium;

        public static YouTubeUri GetBestVideoUri(IEnumerable<YouTubeUri> uris, VideoQuality minQuality, VideoQuality maxQuality)
        {
            return Enumerable.FirstOrDefault<YouTubeUri>((IEnumerable<YouTubeUri>)Enumerable.OrderByDescending<YouTubeUri, int>(from u in uris select u, delegate(YouTubeUri u)
            {
                return u.Itag;
            }));
        }

        public static Uri GetThumbnailUri(string youTubeId, YouTubeThumbnailSize size = YouTubeThumbnailSize.Small)
        {
            switch (size)
            {
                case YouTubeThumbnailSize.Small:
                    return new Uri("http://img.youtube.com/vi/" + youTubeId + "/default.jpg", (UriKind)UriKind.Absolute);

                case YouTubeThumbnailSize.Medium:
                    return new Uri("http://img.youtube.com/vi/" + youTubeId + "/hqdefault.jpg", (UriKind)UriKind.Absolute);

                case YouTubeThumbnailSize.Large:
                    return new Uri("http://img.youtube.com/vi/" + youTubeId + "/maxresdefault.jpg", (UriKind)UriKind.Absolute);
            }
            throw new Exception();
        }

        public async static Task<List<YouTubeUri>> GetUrisAsync(string youTubeId, CancellationTokenSource cancelTask)
        {
            using (HttpClient client = new HttpClient())
            {
                client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A406 Safari/8536.25");
                client.DefaultRequestHeaders.Add("Referrer", string.Format("http://m.youtube.com/watch?v={0}", youTubeId));
                DateTime now = DateTime.Now;
                string url=string.Format("http://m.youtube.com/watch?ajax=1&tsp=1&v={0}&dummy={1}&layout=mobile", youTubeId, now.Ticks);
                HttpResponseMessage response = await client.GetAsync(url, cancelTask.Token).ConfigureAwait(false);
                TaskCompletionSource<YouTubeUri[]> task = new TaskCompletionSource<YouTubeUri[]>();
                string introduced13 = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                response.Dispose();
              
                var result = await GetMobileVideoUris(introduced13).ConfigureAwait(false);
                introduced13 = null;
                return result;
            }
        }

     
   
     static async Task<List<YouTubeUri>> GetMobileVideoUris(string content)
        {
            List<YouTubeUri> youTubeUris;
            string str1 = content;
            JObject jObjects = null;
            try
            {
                str1 = str1.Remove(0, 4);
                jObjects = JObject.Parse(str1);
                JToken item = jObjects["content"]["player_data"]["fmt_stream_map"];
                JToken jTokens = jObjects["content"]["player_data"]["player_vars"];
                if (item != null || jTokens != null)
                {
                    List<YouTubeUri> youTubeUris1 = new List<YouTubeUri>();
                    if (item == null || !(jTokens["use_cipher_signature"].JsonValueToString() == "False"))
                    {
                        youTubeUris = parseUrlEncodedFmtStream(jTokens["url_encoded_fmt_stream_map"].JsonValueToString());
                    }
                    else
                    {
                        foreach (JToken jTokens1 in (IEnumerable<JToken>)item)
                        {
                            YouTubeUri youTubeUri = new YouTubeUri()
                            {
                                url = jTokens1["url"].JsonValueToString(),
                                Itag = jTokens1["itag"].JsonValueToInt(),
                                Type = jTokens1["type"].JsonValueToString()
                            };
                            youTubeUris1.Add(youTubeUri);
                        }
                        youTubeUris = youTubeUris1;
                    }
                }
                else
                {
                    youTubeUris = null;
                }
            }
            catch
            {
                youTubeUris = null;
            }
            jObjects = null;
            content = null;
           
            return youTubeUris;
        }

        private static List<YouTubeUri> parseUrlEncodedFmtStream(string encodedStream)
        {
            List<YouTubeUri> youTubeUris;
            List<YouTubeUri> youTubeUris1 = new List<YouTubeUri>();
            try
            {
                string str = encodedStream.Replace(", ", "");
                string[] strArrays1 = str.Split(new char[] { ',' });
                for (int i = 0; i < (int)strArrays1.Length; i++)
                {
                    string str1 = strArrays1[i];
                    List<Tuple<string, string>> tuples = new List<Tuple<string, string>>();
                    char[] chrArray = new char[] { '&' };




                    // New version to universal Apps
                    foreach (string kvp in (IEnumerable<string>)str1.Split(chrArray, StringSplitOptions.RemoveEmptyEntries))
                    {
                        string[] strArrays = kvp.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
                        if (strArrays == null || ((IEnumerable<string>)strArrays).Count<string>() != 2)
                        {
                            return null;
                        }
                        tuples.Add(new Tuple<string, string>(strArrays[0], strArrays[1]));
                    }

                  
                    if (tuples.Count > 0)
                    {
                        YouTubeUri youTubeUri = new YouTubeUri();
                        string empty = string.Empty;
                        foreach (Tuple<string, string> tuple in tuples)
                        {
                            string item1 = tuple.Item1;
                            string str2 = item1;
                            if (item1 == null)
                            {
                                continue;
                            }
                            if (str2 == "url")
                            {
                                youTubeUri.url = WebUtility.UrlDecode(tuple.Item2);
                            }
                            else if (str2 == "itag")
                            {
                                youTubeUri.Itag = Convert.ToInt32(tuple.Item2);
                            }
                            else if (str2 == "type")
                            {
                                if (tuple.Item2.Contains("m4a"))
                                {
                                    Debug.WriteLine(tuple.Item2);
                                }
                                if (!tuple.Item2.Contains("video%2Fmp4") && !tuple.Item2.Contains("video%2F3gp"))
                                {
                                    continue;
                                }
                                youTubeUri.Type = tuple.Item2;
                            }
                        }
                        if (youTubeUri.Uri != null)
                        {
                            if (!youTubeUri.url.Contains("ratebypass"))
                            {
                                youTubeUri.url = string.Concat(youTubeUri.url, "&ratebypass=yes");
                            }
                            if (youTubeUri.IsValid)
                            {
                                youTubeUris1.Add(youTubeUri);
                            }
                        }
                    }
                }
                if (youTubeUris1.Count <= 0)
                {
                    return null;
                }
                str = null;
                strArrays1 = null;
                return youTubeUris1;
            }
            catch
            {
                youTubeUris = null;
            }
           
            return youTubeUris;
        }

    
    }
}